<template>
    <!-- <div class="contract_box">
        <div class="contract_top">
            <i class="glyphicon glyphicon-info-sign"></i> 
            <span>Are you the contract creator? <router-link to="/verifyContract">Verify and Publish</router-link> your contract source code today!</span>
        </div>
    </div> -->
    <div class="isVerified">
        <div>
            <el-button v-if="code == true" @click="() => { this.tabs = 0 }" :type="tabs === 0 ? 'primary' : ''"
                size="small">Code</el-button>
            <el-button @click="onTabs1" :type="tabs === 1 ? 'primary' : ''" size="small">Read Contract</el-button>
            <el-button @click="onTabs2" :type="tabs === 2 ? 'primary' : ''" size="small">Write Contract</el-button>
        </div>

        <div v-if="code == true && this.tabs == 0 && this.data">
            <p class="flex_ai">
                <el-icon color="#00c9a7">
                    <CircleCheckFilled />
                </el-icon>
                Contract Source Code Verified <span class="small">(Exact Match)</span>
            </p>
            <el-row class="exact">
                <el-col :md="12">
                    <el-row>
                        <el-col :md="8">Contract Name:</el-col>
                        <el-col :md="16">{{ data.contractName }}</el-col>
                    </el-row>
                </el-col>
                <el-col :md="12">
                    <el-row>
                        <el-col :md="10">Optimization Enabled:</el-col>
                        <el-col :md="14">{{ data.optimizationEnabled }}</el-col>
                    </el-row>
                </el-col>
                <el-col :md="12">
                    <el-row>
                        <el-col :md="8">Compiler Version:</el-col>
                        <el-col :md="16">{{ data.compilerVersion }}</el-col>
                    </el-row>
                </el-col>
                <el-col :md="12">
                    <el-row>
                        <el-col :md="8">Other Settings:</el-col>
                        <el-col :md="16">{{ data.otherSettings }}</el-col>
                    </el-row>
                </el-col>
            </el-row>

            <div class="contract_ipt">
                <!-- <p> -->
                <div>
                    <p>
                        <el-icon>
                            <Document />
                        </el-icon>Contract Source Code <span>(Solidity)</span>
                    </p>
                    <div @click="() => { clickBtn(datas.source) }"
                        style="float:right;cursor: pointer;display: flex;align-items: center;">
                        <img src="../../../assets/img/copy.svg" alt="" />
                        <span class="c999">(copy)</span>
                    </div>
                </div>
                <!-- </p> -->
                <el-input disabled type="textarea" :autosize="{ minRows: 2, maxRows: 12 }" v-model="datas.source">
                </el-input>
            </div>

            <div class="contract_ipt">
                <div>
                    <p>Contract ABI</p>
                    <div @click="() => { clickBtn(datas.abi) }"
                        style="float:right;cursor: pointer;display: flex;align-items: center;">
                        <img src="../../../assets/img/copy.svg" alt="" />
                        <span class="c999">(copy)</span>
                    </div>
                </div>
                <el-input disabled type="textarea" :autosize="{ minRows: 2, maxRows: 12 }" v-model="datas.abi">
                </el-input>
            </div>

            <div class="contract_ipt">
                <div>
                    <p>Contract Creation Code</p>
                    <div @click="() => { clickBtn(datas.byteCode) }"
                        style="float:right;cursor: pointer;display: flex;align-items: center;">
                        <img src="../../../assets/img/copy.svg" alt="" />
                        <span class="c999">(copy)</span>
                    </div>
                </div>
                <el-input disabled type="textarea" :autosize="{ minRows: 2, maxRows: 12 }" v-model="datas.byteCode">
                </el-input>
            </div>

            <div class="contract_ipt">
                <div>
                    <p>Constructor Arguments
                        <span>(ABI-Encoded and is the last bytes of the Contract Creation Code above)</span>
                    </p>
                    <div @click="() => { clickBtn(datas.params) }"
                        style="float:right;cursor: pointer;display: flex;align-items: center;">
                        <img src="../../../assets/img/copy.svg" alt="" />
                        <span class="c999">(copy)</span>
                    </div>
                </div>
                <el-input disabled type="textarea" :autosize="{ minRows: 2, maxRows: 12 }" v-model="datas.params">
                </el-input>
            </div>
        </div>

        <div v-if="this.tabs == 1" class="read_contract">
            <div v-if="abiList.length > 0">
                <p class="flex_ai"><el-icon>
                        <Document />
                    </el-icon> Read Contract Information</p>
                <el-collapse v-model="activeNames1" @change="handleChange">
                    <el-collapse-item :name="i" class="m_collapse" v-for="(item, i) in this.abiList" :key="i">
                        <template #title>
                            <div class="pad_l1">{{ i + 1 }}. {{ item.name }}</div>
                        </template>
                        <div class="pad1">
                            <div v-if="item.inputs.length > 0">
                                <div v-for="(items, x) in item.inputs" :key="x" class="ipt_box">
                                    <p>{{ items.name }} ({{ items.type }})</p>
                                    <el-input type="text" v-model="this.abiList[i].inputs[x].val" value=""
                                        :placeholder="items.name + ' ' + '(' + items.type + ')'" />
                                </div>
                                <el-button @click="onQuery(i, item.name)" type="info" plain>Query</el-button>
                            </div>
                            <div v-if="item.outputs.length > 0">
                                <div v-for="(items, x) in item.outputs" :key="x" class="ipt_box">
                                    <p><img src="@/assets/img/shape-1.svg" /> {{ items.name }} <span
                                            style="color:#6c757d">({{ items.type }})</span></p>

                                    <div>
                                        <div v-if="item.value !== null">
                                            <p>[ <i class="bold">
                                                    {{ item.name }}
                                                    (<span v-for="(items1, x1) in item.inputs" :key="x1"><u
                                                            v-if="x1 !== 0">,</u>{{ items1.type }} </span>)
                                                </i> method Response ]
                                            </p>
                                            <p style="margin:10px 0"><el-icon color="#28a745">
                                                    <DArrowRight />
                                                </el-icon>
                                                <i class="bold">{{ items.name }}</i>
                                                {{ items.type }} :
                                                <span v-if="item.outputs.length == 1">{{ item.value }}</span>
                                                <span v-if="item.outputs.length > 1">
                                                    {{ item.value[x] }}
                                                </span>
                                            </p>
                                        </div>
                                        <div v-if="item.err !== null" style="color:red">
                                            {{ item.err }}
                                        </div>
                                    </div>

                                </div>
                            </div>
                        </div>
                    </el-collapse-item>
                </el-collapse>
            </div>
            <div class="notdata" v-else>
                Not Data
            </div>
        </div>

        <div v-if="this.tabs == 2" class="read_contract">
            <div v-if="abiListWrite.length > 0">
                <div class="flex_ai connect" style="justify-content: space-between">
                    <span v-if="accounts === ''" @click="onConnect"><i></i> Connect to Web3</span>
                    <span v-if="accounts !== ''" class="connect_span"><i></i> Connected - Web3
                        [{{ this.subAddress(accounts) }}]</span>
                    <p @click="onReset">[Reset]</p>
                </div>
                <el-collapse v-model="activeNames2">
                    <el-collapse-item :name="i" class="m_collapse" v-for="(item, i) in this.abiListWrite" :key="i">
                        <template #title>
                            <div class="pad_l1">{{ i + 1 }}. {{ item.name }}</div>
                        </template>
                        <div class="pad1">
                            <div v-if="item.inputs.length >= 0">
                                <div v-for="(items, x) in item.inputs" :key="x" class="ipt_box">
                                    <p>{{ items.name }} ({{ items.type }})</p>
                                    <el-input type="text" v-model="this.abiListWrite[i].inputs[x].val" value=""
                                        :placeholder="items.name + ' ' + '(' + items.type + ')'" />

                                </div>
                                <el-button @click="onWrite(i, item.name)" type="primary">Write</el-button>
                                <span v-if="item.loading" class="pad_l1">loading...</span>
                                <!-- <router-link :to="'/tx/'+item.hash">{{$utils.subAddress(item.hash)}}</router-link> -->
                                <span class="write_span">
                                    <el-button v-if="item.hash" type="primary"><router-link :to="'/tx/' + item.hash"> view
                                            in
                                            browse </router-link></el-button>
                                </span>
                                <div v-if="item.err !== null" style="color:red">
                                    {{ item.err }}
                                </div>
                            </div>
                            <!-- <div v-if="item.outputs.length >= 0">
                            <div v-for="(items,x) in item.outputs" :key="x" class="ipt_box">
                                <div v-if="item.err !== null" style="color:red">)
                                    {{item.err}}
                                </div>
                            </div>
                        </div> -->
                        </div>
                    </el-collapse-item>
                </el-collapse>
            </div>
            <div class="notdata" v-else>
                Not Data
            </div>
        </div>

    </div>
</template>

<script>
import Web3 from 'web3'
import { CircleCheckFilled, Document, DArrowRight, DocumentCopy } from "@element-plus/icons-vue"
import useClipboard from 'vue-clipboard3'
import BigNumber from 'bignumber.js'
import { ElMessage } from 'element-plus'
// import { subAddress } from '@/utils/util'

export default {
    props: ['data', 'code'],
    data() {
        return {
            datas: this.data,
            inputData: [],
            tabs: 1,
            abiList: [],
            abiListWrite: [],
            accounts: '',
            loading: true,
            hash: null
        }
    },
    computed: {
        //过滤出满足条件后的数据再渲染
    },
    mounted() {


        console.log(this.data)
        if (this.code) {
            this.tabs = 0
        }
        console.log('this.code')
        console.log(this.code)
        if (window.web3js && this.datas.abi) {
            window.MyContract = new window.web3js.eth.Contract(JSON.parse(this.datas.abi), this.$route.params.id);
            console.log('window.MyContract')
            console.log(window.MyContract)

            this.abiList = this.getAbiList()
            console.log(this.abiList)
            this.abiListWrite = this.getAbiListWrite()
            // console.log(JSON.parse(this.datas.abi))
            console.log('this.abiList')
            // console.log(this.abiListWrite)
        }



    },
    methods: {
        subAddress(str, idx = 8) {
            if (str.length > 30) {
                return str.slice(0, idx) + '....' + str.substring(str.length - (idx - 2), str.length)
            } else {
                return str
            }
        },
        onTabs1() {
            this.tabs = 1
        },
        onTabs2() {
            this.tabs = 2
            // if(window.web3){
            //     window.web3Contract =new window.web3.eth.Contract(JSON.parse(this.datas.abi),this.$route.params.id);
            //     console.log(window.web3Contract)
            // }
        },
        async handleChange(item) {
            // console.log(item.length)
            let i = item[item.length - 1]
            console.log(i)
            console.log(this.abiList)
            console.log(...this.inputData)
            if (i !== undefined && this.abiList[i].inputs.length == 0) {
                try {
                    let a = await window.MyContract.methods[this.abiList[i].name]().call()
                    console.log('a')
                    console.log(a)
                    this.abiList[i].value = a
                    this.abiList[i].err = null
                } catch (err) {
                    this.abiList[i].err = err.toString()
                    this.abiList[i].value = null
                }
            }
        },
        onConnect() {
            //判断用户是否安装MetaMask钱包插件
            if (typeof window.ethereum === "undefined") {
                //没安装MetaMask钱包进行弹框提示
                ElMessage.warning("please open MetaMask")
            } else {
                var _that = this
                //如果用户安装了MetaMask，你可以要求他们授权应用登录并获取其账号
                window.ethereum.enable().catch(function (reason) {
                    //如果用户拒绝了登录请求
                    if (reason === "User rejected provider access") {
                        alert("User rejected provider access")
                        // 用户拒绝登录后执行语句；
                    } else {
                        // 本不该执行到这里，但是真到这里了，说明发生了意外
                        alert("There was a problem signing you in")
                        // Message.warning("There was a problem signing you in");
                    }
                }).then(function (accounts) {
                    // if(undefined)
                    // if (ethereum.networkVersion !== "1281") {
                    //     alert('请切换至1281gc网络')
                    // }
                    const web3 = new Web3(window.ethereum);
                    // window.webContract = new Contract(JSON.parse(_that.datas.abi), _that.$route.params.id)
                    // 判断是否连接以太
                    window.web3Contract = new web3.eth.Contract(JSON.parse(_that.datas.abi), _that.$route.params.id);
                    window.web3 = web3
                    console.log("Injected web3 detected.");
                    console.log(window.web3Contract);
                    // console.log(window.webContract);
                    // let currentProvider = web3.currentProvider;
                    // window.web3js.setProvider(currentProvider);
                    //如果用户同意了登录请求，你就可以拿到用户的账号
                    console.log(accounts)
                    _that.accounts = accounts[0];
                    window.accounts = accounts[0];
                    // console.log(window.account)
                });
            }
        },
        getAbiList: function () {
            let arr = JSON.parse(this.datas.abi)
            return arr.filter(function (item) {
                // console.log(item)
                // console.log(i)
                if (item.type == 'function' && (item.stateMutability == 'view' || item.stateMutability == 'pure')) {
                    if (item.inputs.length > 0) {
                        item.inputs.forEach((element) => {
                            // console.log(element)
                            element.val = ''
                        });
                    }
                    item.err = null
                    item.value = null
                    return item
                }
            })
        },
        getAbiListWrite: function () {
            let arr = JSON.parse(this.datas.abi)
            return arr.filter(function (item) {

                // console.log(i)
                if (item.type == 'function' && (item.stateMutability == 'nonpayable' || item.stateMutability == 'payable')) {
                    if (item.stateMutability == 'payable') {
                        console.log(item)
                        item.inputs.push({
                            name: "payableAmount",
                            type: "TOK",
                            internalType: "TOK",
                            val: ""
                        })
                    }
                    if (item.inputs.length > 0) {
                        item.inputs.forEach((element) => {
                            element.val = ''
                        });
                    }
                    item.err = ''
                    item.value = null
                    item.hash = null
                    item.loading = false
                    return item
                }
            })
        },
        async onQuery(i, name) {
            // console.log(name)
            let arr = [];
            this.abiList[i].inputs.forEach((item, x) => {
                arr[x] = item.val
            });
            this.inputData = arr
            // console.log(this.inputData)
            // console.log(...this.inputData)
            try {
                let a = await window.MyContract.methods[name](...this.inputData).call()
                this.abiList[i].value = a
                this.abiList[i].err = null
                console.log('a')
                console.log(a)
            } catch (err) {
                this.abiList[i].err = err.toString()
                this.abiList[i].value = null
                console.log(this.abiList)
            }
        },
        onWrite(i, name) {
            if (this.accounts == '') {
                alert('Please connect the wallet and operate')
                return false
            }
            this.abiListWrite[i].err = null
            this.abiListWrite[i].loading = true
            this.abiListWrite[i].hash = null
            // console.log('this.abiListWrite---点击')
            console.log(this.abiListWrite)
            // console.log(i)
            let arr = [];
            let value = 0
            this.abiListWrite[i].inputs.forEach((item, x) => {
                arr[x] = item.val
            });
            if (this.abiListWrite[i].stateMutability == "payable") {
                value = new BigNumber(arr.pop() * Math.pow(10, 18))
            }
            this.inputData = arr
            try {
                window.web3Contract.methods[name](...this.inputData).send({ from: window.accounts, value: value }, async (err, hash) => {
                    console.log('hash', hash)
                    console.log('err', err)
                    if (hash && hash.length > 0) {

                        const status_checker = setInterval(async () => {
                            const tx = await window.web3.eth.getTransaction(hash)
                            console.log({ getTransaction: tx })
                            if (!(typeof tx.blockHash == 'object' && tx.blockHash === null)) {
                                const txrt = await window.web3.eth.getTransactionReceipt(hash)
                                console.log({ getTransactionReceipt: txrt })
                                clearInterval(status_checker)
                                switch (txrt.status) {
                                    case true:
                                        console.log('ok')
                                        this.abiListWrite[i].hash = hash
                                        this.abiListWrite[i].loading = false
                                        this.abiListWrite[i].err = null
                                        break
                                    default:
                                        this.abiListWrite[i].hash = hash
                                        console.log('err')
                                        this.abiListWrite[i].loading = false
                                        break
                                }
                            }
                        }, 1000)

                    }
                }).then((res) => {
                    if (res.status === true) {
                        console.log('finally', res)
                    } else {
                        console.log('then (not success)', res)
                    }
                    this.abiListWrite[i].loading = false
                }, (failure) => {
                    this.abiListWrite[i].loading = false
                    // if (failure.code === 4001) {
                    //     this.abiListWrite[i].err = failure.message
                    // }
                    this.abiListWrite[i].err = failure.message
                    console.log('failure', failure.code, failure.message) //code: 4001, message: user cancelled
                })
            } catch (err) {
                console.log('err1', err)
                this.abiListWrite[i].err = err.toString()
                this.abiListWrite[i].loading = false
            }

        },
        onReset() {
            window.location.reload()
        },
        clickBtn: async function (text) {
            // alert(text)
            const { toClipboard } = useClipboard()
            try {
                await toClipboard(text)
                ElMessage({
                    message: 'Copy success',
                    type: 'success',
                })
            } catch (e) {
                ElMessage({
                    message: 'Copy error',
                    type: 'error',
                })
            }
        }
    },
    components: {
        CircleCheckFilled,
        Document,
        DArrowRight,
        DocumentCopy
    }
}
</script>

<style lang="less" scoped>
.isVerified {
    padding-top: 10px;

    :deep(.el-textarea__inner) {
        color: var(--color-text);
        font-size: 0.7rem;
        line-height: 1.2rem
    }

    .exact {
        font-size: 0.85rem;
        margin-bottom: 3rem;

        .el-row {
            border-bottom: 1px solid var(--color-border);
        }

        .el-col {
            line-height: 40px;

        }
    }

    .read_contract {
        :deep(.el-collapse-item__header) {
            background: #f8f9fa;
            padding: 10px;
        }

        :deep(.el-collapse-item__wrap) {
            padding: 10px;
        }

        .flex_ai p {
            color: #409eff;
            cursor: pointer;
        }

        .el-collapse {
            border: 0;
        }

        .m_collapse {
            margin-bottom: 1rem;
            --el-collapse-header-background-color: #f8f9fa;
            --el-collapse-border-color: #ddd;
            border-left: 1px solid #eee;
            border-right: 1px solid #eee;

            .ipt_box {
                margin: 1.5rem 0;

                p {
                    margin-bottom: .5rem;
                    color: #6c757d;
                }

                img {
                    width: 10px;
                    display: inline-block;
                    margin-right: .5rem;
                }
            }

            .write_span {
                display: inline-block;
                margin-left: 1rem;

                a {
                    color: #fff;
                }
            }
        }

        .connect {
            font-size: 0.9rem;

            span {
                background: #777;
                color: #fff;
                padding: 4px 15px;
                border-radius: .2rem;
                font-size: 0.8rem;
                cursor: pointer;
                opacity: .8;
                display: flex;
                align-items: center;

                i {
                    background: red;
                    display: inline-block;
                    width: 12px;
                    height: 12px;
                    border-radius: 50%;
                    margin-right: 4px;
                }


            }

            .connect_span {
                background: #20941f;

                i {
                    background: #05e602;
                }
            }

        }

    }

    .flex_ai {
        display: flex;
        align-items: center;
        gap: 2px;
        padding-right: 1rem;
        font-size: 1rem;
        margin: 2.5rem 0 1rem;

        span {
            color: var(--color-text2);
            font-size: 0.8rem;
            padding-left: 5px;
            font-weight: normal;
        }
    }

    .contract_ipt {
        div {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 15px;

            p {
                font-size: 0.9rem;

                span {
                    color: var(--color-text2);
                    font-size: 0.8rem;
                    padding-left: 5px;
                    font-weight: normal;
                }
            }
        }


    }

    // .col-md-6 {
    //     margin: 0 0 1.5rem;
    //     padding-bottom: 1.5rem;
    //     border-bottom: 1px solid #eee;
    // }
}
</style>